const path = require('path');
const axios = require('axios');
const log4js = require('log4js');
const express = require('express');
const short = require('short-uuid');
const bodyParser = require('body-parser');
const ConnectCas = require('connect-cas2');
const session = require('express-session');
const compression = require('compression');
const cookieParser = require('cookie-parser');
const config = require('../config/config.js');
const MemoryStore = require('session-memory-store')(session);

const app = express();
const translator = short();
const logger = log4js.getLogger();

// Configure log4j
log4js.configure({
  appenders: {
    dateFile: {
      type: 'dateFile',
      filename: 'aab',
      pattern: '-yyyy-MM-dd.log',
      alwaysIncludePattern: true,
    },
    out: {type: 'stdout'},
  },
  categories: {
    default: {appenders: ['dateFile', 'out'], level: 'debug'},
  },
});

// Dev: If you want to dev locally, Please use this function middleware. DO NOT push it to PRD
app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000'); // This origin is UI dev server
  res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  res.setHeader('Access-Control-Allow-Credentials', true);
  next();
});

app.use(compression());
app.use(cookieParser());
app.use(session({name: 'NSESSIONID', secret: 'Hello I am a long long long secret', store: new MemoryStore()}));

app.use((req, res, next) => {
  req.sn = translator.uuid();
  next();
});

// Init CAS client
const casClient = new ConnectCas({
  // debug: true,
  ignore: [/\/ignore/, /\/favicon.ico/, /\/assets/, /\/beats/],
  match: [],
  servicePrefix: config.SERVICE_URL,
  serverPath: config.CAS_URL,
  paths: {
    validate: '/validate',
    serviceValidate: '/serviceValidate',
    proxy: '',
    login: '/login',
    logout: '/logout',
    proxyCallback: false,
  },
  restletIntegration: false,
  redirect: false,
  gateway: false,
  renew: false,
  slo: true,
  cache: {
    enable: false,
    ttl: 5 * 60 * 1000,
    filter: [],
  },
  fromAjax: {
    header: 'x-client-ajax',
    status: 418,
  },
});

// Prd
// app.use(casClient.core());

// Check and save session && token
app.use(async (req, res, next) => {
  // Dev
  req.session.cas = {user: 'czhou'};

  if (req.session && req.session.cas) {
    const userName = req.session.cas.user;
    const {
      SERVICE_URL,
      UC_BACKEND_API: {TYPE, HOST, PORT},
    } = config;
    try {
      const requestUrl = `${TYPE}://${HOST}:${PORT}/principal`;
      const response = await axios.get(requestUrl, {params: {login: userName, appurl: SERVICE_URL}});
      if (!response.data.hasOwnProperty('error')) {
        req.session.principal = response.data;
        next();
      } else {
        logger.error('get principal error!');
      }
    } catch (error) {
      logger.error(error.message);
    }
  } else {
    logger.error("This check session log shouldn't appear!");
    next();
  }
});

// NOTICE: If you want to enable single sign logout, you must use casClient middleware before bodyParser.
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());

// Logout Logic: Will destroy the session of current user and then redirect to the CAS server logout page.
app.get('/logout', function(req, res, next) {
  logger.info('Doing Logout...');
  req.session.principal = null; // Clear Printciapl
  casClient.logout()(req, res, next);
});

// Configure static folder
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, '/../build')));

// Configure controller router
//TODO

// Send resource
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, '/../build', 'index.html'));
});

// App start
const port = process.env.PORT || 3005;
app.listen(port, () => {
  logger.info(`app listening on port: ${port}`);
});
